home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / sd-26.zip / sdpreds.c < prev    next >
C/C++ Source or Header  |  1992-09-09  |  37KB  |  985 lines

  1. /* SD -- square dance caller's helper.
  2.  
  3.     Copyright (C) 1990, 1991, 1992  William B. Ackerman.
  4.  
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 1, or (at your option)
  8.     any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19.     This is version 24.0. */
  20.  
  21. /* This defines the following function:
  22.    selectp
  23.  
  24. and the following external variables:
  25.    current_selector
  26.    selector_used
  27.    pred_table     which is filled with pointers to the predicate functions
  28. */
  29.  
  30. #include "sd.h"
  31.  
  32. /* These variables are external. */
  33.  
  34. selector_kind current_selector;
  35. long_boolean selector_used;
  36.  
  37.  
  38. /* If a real person and a person under test are XOR'ed, the result AND'ed with this constant,
  39.    and the low bits of that result examined, it will tell whether the person under test is real
  40.    and facing in the same direction (result = 0), the opposite direction (result == 2), or whatever. */
  41.  
  42. #define DIR_MASK (BIT_PERSON | 3)
  43.  
  44. #define ID2_ALL_ID (ID2_HEAD|ID2_SIDE|ID2_BOY|ID2_GIRL)
  45.  
  46.  
  47.  
  48.  
  49.  
  50. extern long_boolean selectp(setup *ss, int place)
  51. {
  52.    int pid2;
  53.  
  54.    selector_used = TRUE;
  55.  
  56.    /* Pull out the cases that do not require the person to be real. */
  57.  
  58.    switch (current_selector) {
  59.       case selector_all:
  60.          return(TRUE);
  61.       case selector_none:
  62.          return(FALSE);
  63.    }
  64.  
  65.    /* Demand that the subject be real. */
  66.  
  67.    if (!(ss->people[place].id1 & BIT_PERSON))
  68.       fail("Can't decide who are selected.");
  69.  
  70.    pid2 = ss->people[place].id2;
  71.  
  72.    switch (current_selector) {
  73.       case selector_boys:
  74.          if      ((pid2 & (ID2_BOY|ID2_GIRL)) == ID2_BOY) return(TRUE);
  75.          else if ((pid2 & (ID2_BOY|ID2_GIRL)) == ID2_GIRL) return(FALSE);
  76.          break;
  77.       case selector_girls:
  78.          if      ((pid2 & (ID2_BOY|ID2_GIRL)) == ID2_GIRL) return(TRUE);
  79.          else if ((pid2 & (ID2_BOY|ID2_GIRL)) == ID2_BOY) return(FALSE);
  80.          break;
  81.       case selector_heads:
  82.          if      ((pid2 & (ID2_HEAD|ID2_SIDE)) == ID2_HEAD) return(TRUE);
  83.          else if ((pid2 & (ID2_HEAD|ID2_SIDE)) == ID2_SIDE) return(FALSE);
  84.          break;
  85.       case selector_sides:
  86.          if      ((pid2 & (ID2_HEAD|ID2_SIDE)) == ID2_SIDE) return(TRUE);
  87.          else if ((pid2 & (ID2_HEAD|ID2_SIDE)) == ID2_HEAD) return(FALSE);
  88.          break;
  89.       case selector_headcorners:
  90.          if      ((pid2 & (ID2_HCOR|ID2_SCOR)) == ID2_HCOR) return(TRUE);
  91.          else if ((pid2 & (ID2_HCOR|ID2_SCOR)) == ID2_SCOR) return(FALSE);
  92.          break;
  93.       case selector_sidecorners:
  94.          if      ((pid2 & (ID2_HCOR|ID2_SCOR)) == ID2_SCOR) return(TRUE);
  95.          else if ((pid2 & (ID2_HCOR|ID2_SCOR)) == ID2_HCOR) return(FALSE);
  96.          break;
  97.       case selector_headboys:
  98.          if      ((pid2 & (ID2_ALL_ID|ID2_NHB)) == (ID2_HEAD|ID2_BOY)) return(TRUE);
  99.          else if ((pid2 & ID2_NHB) == ID2_NHB) return(FALSE);
  100.          break;
  101.       case selector_headgirls:
  102.          if      ((pid2 & (ID2_ALL_ID|ID2_NHG)) == (ID2_HEAD|ID2_GIRL)) return(TRUE);
  103.          else if ((pid2 & ID2_NHG) == ID2_NHG) return(FALSE);
  104.          break;
  105.       case selector_sideboys:
  106.          if      ((pid2 & (ID2_ALL_ID|ID2_NSB)) == (ID2_SIDE|ID2_BOY)) return(TRUE);
  107.          else if ((pid2 & ID2_NSB) == ID2_NSB) return(FALSE);
  108.          break;
  109.       case selector_sidegirls:
  110.          if      ((pid2 & (ID2_ALL_ID|ID2_NSG)) == (ID2_SIDE|ID2_GIRL)) return(TRUE);
  111.          else if ((pid2 & ID2_NSG) == ID2_NSG) return(FALSE);
  112.          break;
  113.       case selector_centers:
  114.          if      ((pid2 & (ID2_CENTER|ID2_END)) == ID2_CENTER) return(TRUE);
  115.          else if ((pid2 & (ID2_CENTER|ID2_END)) == ID2_END) return(FALSE);
  116.          break;
  117.       case selector_ends:
  118.          if      ((pid2 & (ID2_CENTER|ID2_END)) == ID2_END) return(TRUE);
  119.          else if ((pid2 & (ID2_CENTER|ID2_END)) == ID2_CENTER) return(FALSE);
  120.          break;
  121.       case selector_leads:
  122.          if      ((pid2 & (ID2_LEAD|ID2_TRAILER)) == ID2_LEAD) return(TRUE);
  123.          else if ((pid2 & (ID2_LEAD|ID2_TRAILER)) == ID2_TRAILER) return(FALSE);
  124.          break;
  125.       case selector_trailers:
  126.          if      ((pid2 & (ID2_LEAD|ID2_TRAILER)) == ID2_TRAILER) return(TRUE);
  127.          else if ((pid2 & (ID2_LEAD|ID2_TRAILER)) == ID2_LEAD) return(FALSE);
  128.          break;
  129.       case selector_beaux:
  130.          if      ((pid2 & (ID2_BEAU|ID2_BELLE)) == ID2_BEAU) return(TRUE);
  131.          else if ((pid2 & (ID2_BEAU|ID2_BELLE)) == ID2_BELLE) return(FALSE);
  132.          break;
  133.       case selector_belles:
  134.          if      ((pid2 & (ID2_BEAU|ID2_BELLE)) == ID2_BELLE) return(TRUE);
  135.          else if ((pid2 & (ID2_BEAU|ID2_BELLE)) == ID2_BEAU) return(FALSE);
  136.          break;
  137.       case selector_center2:
  138.          if      ((pid2 & (ID2_CTR2|ID2_OUTR6)) == ID2_CTR2) return(TRUE);
  139.          else if ((pid2 & (ID2_CTR2|ID2_OUTR6)) == ID2_OUTR6) return(FALSE);
  140.          break;
  141.       case selector_center6:
  142.          if      ((pid2 & (ID2_CTR6|ID2_OUTR2)) == ID2_CTR6) return(TRUE);
  143.          else if ((pid2 & (ID2_CTR6|ID2_OUTR2)) == ID2_OUTR2) return(FALSE);
  144.          break;
  145.       case selector_outer2:
  146.          if      ((pid2 & (ID2_CTR6|ID2_OUTR2)) == ID2_OUTR2) return(TRUE);
  147.          else if ((pid2 & (ID2_CTR6|ID2_OUTR2)) == ID2_CTR6) return(FALSE);
  148.          break;
  149.       case selector_outer6:
  150.          if      ((pid2 & (ID2_CTR2|ID2_OUTR6)) == ID2_OUTR6) return(TRUE);
  151.          else if ((pid2 & (ID2_CTR2|ID2_OUTR6)) == ID2_CTR2) return(FALSE);
  152.          break;
  153.       case selector_nearline:
  154.          if      ((pid2 & (ID2_NEARLINE|ID2_FARLINE)) == ID2_NEARLINE) return(TRUE);
  155.          else if ((pid2 & (ID2_NEARLINE|ID2_FARLINE)) == ID2_FARLINE) return(FALSE);
  156.          break;
  157.       case selector_farline:
  158.          if      ((pid2 & (ID2_NEARLINE|ID2_FARLINE)) == ID2_FARLINE) return(TRUE);
  159.          else if ((pid2 & (ID2_NEARLINE|ID2_FARLINE)) == ID2_NEARLINE) return(FALSE);
  160.          break;
  161.       case selector_nearcolumn:
  162.          if      ((pid2 & (ID2_NEARCOL|ID2_FARCOL)) == ID2_NEARCOL) return(TRUE);
  163.          else if ((pid2 & (ID2_NEARCOL|ID2_FARCOL)) == ID2_FARCOL) return(FALSE);
  164.          break;
  165.       case selector_farcolumn:
  166.          if      ((pid2 & (ID2_NEARCOL|ID2_FARCOL)) == ID2_FARCOL) return(TRUE);
  167.          else if ((pid2 & (ID2_NEARCOL|ID2_FARCOL)) == ID2_NEARCOL) return(FALSE);
  168.          break;
  169.       case selector_nearbox:
  170.          if      ((pid2 & (ID2_NEARBOX|ID2_FARBOX)) == ID2_NEARBOX) return(TRUE);
  171.          else if ((pid2 & (ID2_NEARBOX|ID2_FARBOX)) == ID2_FARBOX) return(FALSE);
  172.          break;
  173.       case selector_farbox:
  174.          if      ((pid2 & (ID2_NEARBOX|ID2_FARBOX)) == ID2_FARBOX) return(TRUE);
  175.          else if ((pid2 & (ID2_NEARBOX|ID2_FARBOX)) == ID2_NEARBOX) return(FALSE);
  176.          break;
  177.       default:
  178.          fail("ERROR - selector failed to get initialized.");
  179.    }
  180.    
  181.    fail("Can't decide who are selected.");
  182.    /* NOTREACHED */
  183. }
  184.  
  185.  
  186.  
  187. /* Here are the predicates.  They will get put into the array "pred_table". */
  188.  
  189. /* ARGSUSED */
  190. static long_boolean selected(setup *real_people, int real_index,
  191.    int real_direction, int northified_index)
  192. {
  193.    return(selectp(real_people, real_index));
  194. }
  195.  
  196. /* ARGSUSED */
  197. static long_boolean unselect(setup *real_people, int real_index,
  198.    int real_direction, int northified_index)
  199. {
  200.    return(!selectp(real_people, real_index));
  201. }
  202.  
  203. /* ARGSUSED */
  204. static long_boolean select_near_select(setup *real_people, int real_index,
  205.    int real_direction, int northified_index)
  206. {
  207.    return(selectp(real_people, real_index) && selectp(real_people, real_index ^ 1));
  208. }
  209.  
  210. /* ARGSUSED */
  211. static long_boolean select_near_unselect(setup *real_people, int real_index,
  212.    int real_direction, int northified_index)
  213. {
  214.    return(selectp(real_people, real_index) && !selectp(real_people, real_index ^ 1));
  215. }
  216.  
  217. /* ARGSUSED */
  218. static long_boolean unselect_near_select(setup *real_people, int real_index,
  219.    int real_direction, int northified_index)
  220. {
  221.    return(!selectp(real_people, real_index) && selectp(real_people, real_index ^ 1));
  222. }
  223.  
  224. /* ARGSUSED */
  225. static long_boolean unselect_near_unselect(setup *real_people, int real_index,
  226.    int real_direction, int northified_index)
  227. {
  228.    return(!(selectp(real_people, real_index) || selectp(real_people, real_index ^ 1)));
  229. }
  230.  
  231. /* ARGSUSED */
  232. static long_boolean always(setup *real_people, int real_index,
  233.    int real_direction, int northified_index)
  234. {
  235.    return(TRUE);
  236. }
  237.  
  238. /* ARGSUSED */
  239. static long_boolean x22_miniwave(setup *real_people, int real_index,
  240.    int real_direction, int northified_index)
  241. {
  242.    int this_person = real_people->people[real_index].id1;
  243.    int other_index = real_index ^ (((real_direction << 1) & 2) ^ 1);
  244.    int other_person = real_people->people[other_index].id1;
  245.    return(((this_person ^ other_person) & DIR_MASK) == 2);
  246. }
  247.  
  248. /* ARGSUSED */
  249. static long_boolean x22_couple(setup *real_people, int real_index,
  250.    int real_direction, int northified_index)
  251. {
  252.    int this_person = real_people->people[real_index].id1;
  253.    int other_index = real_index ^ (((real_direction << 1) & 2) ^ 1);
  254.    int other_person = real_people->people[other_index].id1;
  255.    return(((this_person ^ other_person) & DIR_MASK) == 0);
  256. }
  257.  
  258. /* ARGSUSED */
  259. static long_boolean x22_facing_someone(setup *real_people, int real_index,
  260.    int real_direction, int northified_index)
  261. {
  262.    int this_person = real_people->people[real_index].id1;
  263.    int other_index = real_index ^ (((real_direction << 1) & 2) ^ 3);
  264.    int other_person = real_people->people[other_index].id1;
  265.    return(((this_person ^ other_person) & DIR_MASK) == 2);
  266. }
  267.  
  268. /* ARGSUSED */
  269. static long_boolean x14_once_rem_miniwave(setup *real_people, int real_index,
  270.    int real_direction, int northified_index)
  271. {
  272.    int this_person = real_people->people[real_index].id1;
  273.    int other_person = real_people->people[real_index ^ 3].id1;
  274.    return(((this_person ^ other_person) & DIR_MASK) == 2);
  275. }
  276.  
  277. /* ARGSUSED */
  278. static long_boolean x14_once_rem_couple(setup *real_people, int real_index,
  279.    int real_direction, int northified_index)
  280. {
  281.    int this_person = real_people->people[real_index].id1;
  282.    int other_person = real_people->people[real_index ^ 3].id1;
  283.    return(((this_person ^ other_person) & DIR_MASK) == 0);
  284. }
  285.  
  286. /* ARGSUSED */
  287. static long_boolean same_in_quad(setup *real_people, int real_index,
  288.    int real_direction, int northified_index)
  289. {
  290.    int this_person = real_people->people[real_index].id1;
  291.    int other_person = real_people->people[real_index ^ 1].id1;
  292.    if (real_people->kind == s_1x6 && real_index >= 2)
  293.       other_person = real_people->people[7 - real_index].id1;
  294.    return(((this_person ^ other_person) & DIR_MASK) == 0);
  295. }
  296.  
  297. /* ARGSUSED */
  298. static long_boolean opp_in_quad(setup *real_people, int real_index,
  299.    int real_direction, int northified_index)
  300. {
  301.    int this_person = real_people->people[real_index].id1;
  302.    int other_person = real_people->people[real_index ^ 1].id1;
  303.    if (real_people->kind == s_1x6 && real_index >= 2)
  304.       other_person = real_people->people[7 - real_index].id1;
  305.    return(((this_person ^ other_person) & DIR_MASK) == 2);
  306. }
  307.  
  308. /* ARGSUSED */
  309. static long_boolean same_in_pair(setup *real_people, int real_index,
  310.    int real_direction, int northified_index)
  311. {
  312.    int this_person = real_people->people[real_index].id1;
  313.    int other_person = real_people->people[real_index ^ 7].id1;
  314.    return(((this_person ^ other_person) & DIR_MASK) == 0);
  315. }
  316.  
  317. /* ARGSUSED */
  318. static long_boolean opp_in_pair(setup *real_people, int real_index,
  319.    int real_direction, int northified_index)
  320. {
  321.    int this_person = real_people->people[real_index].id1;
  322.    int other_person = real_people->people[real_index ^ 7].id1;
  323.    return(((this_person ^ other_person) & DIR_MASK) == 2);
  324. }
  325.  
  326. /* ARGSUSED */
  327. static long_boolean opp_in_magic(setup *real_people, int real_index,
  328.    int real_direction, int northified_index)
  329. {
  330.    int this_person = real_people->people[real_index].id1;
  331.    int other_person = real_people->people[real_index ^ 6].id1;
  332.    return(((this_person ^ other_person) & DIR_MASK) == 2);
  333. }
  334.  
  335. /* ARGSUSED */
  336. static long_boolean same_in_magic(setup *real_people, int real_index,
  337.    int real_direction, int northified_index)
  338. {
  339.    int this_person = real_people->people[real_index].id1;
  340.    int other_person = real_people->people[real_index ^ 6].id1;
  341.    return(((this_person ^ other_person) & DIR_MASK) == 0);
  342. }
  343.  
  344. /* ARGSUSED */
  345. static long_boolean lines_once_rem_miniwave(setup *real_people, int real_index,
  346.    int real_direction, int northified_index)
  347. {
  348.    int this_person = real_people->people[real_index].id1;
  349.    int other_person = real_people->people[real_index ^ 2].id1;
  350.    return(((this_person ^ other_person) & DIR_MASK) == 2);
  351. }
  352.  
  353. /* ARGSUSED */
  354. static long_boolean lines_once_rem_couple(setup *real_people, int real_index,
  355.    int real_direction, int northified_index)
  356. {
  357.    int this_person = real_people->people[real_index].id1;
  358.    int other_person = real_people->people[real_index ^ 2].id1;
  359.    return(((this_person ^ other_person) & DIR_MASK) == 0);
  360. }
  361.  
  362. /* Next test is used for figuring out how to hinge. */
  363. /* Legal from 1x2. */
  364. /* Returns TRUE if this person is beau, or else this belle is in a miniwave with
  365.    the other person.  Returns FALSE if this belle is in a couple with the
  366.    other person.  Complains if this belle can't tell. */
  367. /* ARGSUSED */
  368. static long_boolean x12_beau_or_miniwave(setup *real_people, int real_index,
  369.    int real_direction, int northified_index)
  370. {
  371.    if (northified_index == 0)
  372.       return(TRUE);
  373.    else {
  374.       int other_person = real_people->people[real_index ^ 1].id1;
  375.       if (!other_person)
  376.          fail("Need a real person to work with."); 
  377.       return (((other_person & 2) >> 1) == real_index);
  378.    }
  379. }
  380.  
  381. /* Test for wheel_and_deal to be done 2FL-style, or beau side of 1FL. */
  382. /* ARGSUSED */
  383. static long_boolean x14_wheel_and_deal_1(setup *real_people, int real_index,
  384.    int real_direction, int northified_index)
  385. {
  386.    int other_person = real_people->people[real_index ^ 1].id1;
  387.  
  388.    /* If person next to me exists, he must face same way as myself. */
  389.    if ((other_person != 0) && (real_direction != (other_person & 3)))
  390.       return(FALSE);
  391.    else if ((northified_index & 2) == 0)
  392.       /* We are in the beau-side couple -- it's OK. */
  393.       return(TRUE);
  394.    else {
  395.       /* We are in the belle-side couple -- find the two people in the other couple. */
  396.       int other_person1 = real_people->people[real_index ^ 2].id1;
  397.       int other_person2 = real_people->people[real_index ^ 3].id1;
  398.  
  399.       /* At least one of those people must exist. */
  400.       if (!(other_person1 || other_person2))
  401.          return(FALSE);
  402.  
  403.       /* Whichever of those people exists must face the opposite way from myself, so
  404.          I can convince myself that I am in a 2FL.*/
  405.  
  406.       if (other_person1 && ((other_person1 ^ real_index) & 2) != 0)
  407.          return(FALSE);
  408.       if (other_person2 && ((other_person2 ^ real_index) & 2) != 0)
  409.          return(FALSE);
  410.  
  411.       return(TRUE);
  412.    }
  413. }
  414.  
  415. /* Test for belle side of 1FL. */
  416.  
  417. /* ARGSUSED */
  418. static long_boolean x14_wheel_and_deal_2(setup *real_people, int real_index,
  419.    int real_direction, int northified_index)
  420. {
  421.    int other_person = real_people->people[real_index ^ 1].id1;
  422.  
  423.    /* If person next to me exists, he must face same way as myself. */
  424.    if ((other_person != 0) && (real_direction != (other_person & 3)))
  425.       return(FALSE);
  426.    else {
  427.       /* Furthermore, assuming we are in the belle-side couple (which we can safely assume
  428.          because of the way this predicate is used in defining Wheel and Deal),
  429.          find the two people in the other couple. */
  430.       int other_person1 = real_people->people[real_index ^ 2].id1;
  431.       int other_person2 = real_people->people[real_index ^ 3].id1;
  432.  
  433.       /* Those people must both exist and face the same way, i.e. we are in a 1FL. */
  434.       if (other_person1 != 0 && other_person2 != 0 &&
  435.             ((other_person1 ^ real_index) & 2) != 0 &&
  436.             ((other_person2 ^ real_index) & 2) != 0)
  437.          return(TRUE);
  438.       else
  439.          return(FALSE);
  440.    }
  441. }
  442.  
  443. static long_boolean vert1(setup *real_people, int real_index,
  444.    int real_direction, int northified_index)
  445. {
  446.    int this_person = real_people->people[real_index].id1;
  447.    int other_person = real_people->people[real_index ^ (((real_direction << 1) & 2) | 1)].id1;
  448.    if (northified_index & 1)
  449.       return(((this_person ^ other_person) & DIR_MASK) == 0);
  450.    else
  451.       return(TRUE);
  452. }
  453.  
  454. static long_boolean vert2(setup *real_people, int real_index,
  455.    int real_direction, int northified_index)
  456. {
  457.    int this_person = real_people->people[real_index].id1;
  458.    int other_person = real_people->people[real_index ^ (((real_direction << 1) & 2) | 1)].id1;
  459.    if (northified_index & 1)
  460.       return(((this_person ^ other_person) & DIR_MASK) == 2);
  461.    else
  462.       return(FALSE);
  463. }
  464.  
  465. /* ARGSUSED */
  466. static long_boolean inner_active_lines(setup *real_people, int real_index,
  467.    int real_direction, int northified_index)
  468. {
  469.    if ((real_index+3) & 2)
  470.       return(northified_index >= 4);     /* I am an end */
  471.    else
  472.       return(                            /* I am a center */
  473.          (012 - ((real_index & 4) >> 1)) == (real_people->people[real_index ^ 1].id1 & 017));
  474. }
  475.  
  476. /* ARGSUSED */
  477. static long_boolean outer_active_lines(setup *real_people, int real_index,
  478.    int real_direction, int northified_index)
  479. {
  480.    if ((real_index+3) & 2)
  481.       return(northified_index < 4);      /* I am an end */
  482.    else
  483.       return(                            /* I am a center */
  484.          (010 + ((real_index & 4) >> 1)) == (real_people->people[real_index ^ 1].id1 & 017));
  485. }
  486.  
  487. /* ARGSUSED */
  488. static long_boolean judge_is_right(setup *real_people, int real_index,
  489.    int real_direction, int northified_index)
  490. {
  491.    int this_person = real_people->people[real_index].id1;
  492.    int f = this_person & 2;
  493.    return(
  494.       (((real_people->people[f ^ 2].id1 ^ this_person) & 013) == 0)       /* judge exists to my right */
  495.          &&
  496.       (((real_people->people[f].id1 ^ this_person) & 013) != 2));         /* we do not have another judge to my left */
  497. }
  498.  
  499. /* ARGSUSED */
  500. static long_boolean judge_is_left(setup *real_people, int real_index,
  501.    int real_direction, int northified_index)
  502. {
  503.    int this_person = real_people->people[real_index].id1;
  504.    int f = this_person & 2;
  505.    return(
  506.       (((real_people->people[f].id1 ^ this_person) & 013) == 2)           /* judge exists to my left */
  507.          &&
  508.       (((real_people->people[f ^ 2].id1 ^ this_person) & 013) != 0));     /* we do not have another judge to my right */
  509. }
  510.  
  511. /* ARGSUSED */
  512. static long_boolean socker_is_right(setup *real_people, int real_index,
  513.    int real_direction, int northified_index)
  514. {
  515.    int this_person = real_people->people[real_index].id1;
  516.    int f = this_person & 2;
  517.    return(
  518.       (((real_people->people[f ^ 2].id1 ^ this_person) & 013) == 2)       /* socker exists to my right */
  519.          &&
  520.       (((real_people->people[f].id1 ^ this_person) & 013) != 0));         /* we do not have another socker to my left */
  521. }
  522.  
  523. /* ARGSUSED */
  524. static long_boolean socker_is_left(setup *real_people, int real_index,
  525.    int real_direction, int northified_index)
  526. {
  527.    int this_person = real_people->people[real_index].id1;
  528.    int f = this_person & 2;
  529.    return(
  530.       (((real_people->people[f].id1 ^ this_person) & 013) == 0)           /* socker exists to my left */
  531.          &&
  532.       (((real_people->people[f ^ 2].id1 ^ this_person) & 013) != 2));     /* we do not have another socker to my right */
  533. }
  534.  
  535. /* ARGSUSED */
  536. static long_boolean inroller_is_cw(setup *real_people, int real_index,
  537.    int real_direction, int northified_index)
  538. {
  539.    int inroll_direction;
  540.  
  541.    inroll_direction = 012 - ((real_index & 4) >> 1);
  542.    if (  /* cw_end exists and is inrolling */
  543.          ((real_people->people[real_index | 3].id1 & 017) == inroll_direction)
  544.       &&
  545.          /* we do not have ccw_end inrolling also */
  546.          ((real_people->people[real_index & 4].id1 & 017) != inroll_direction))
  547.       return(TRUE);
  548.    else if (
  549.          /* ccw_end exists and is inrolling */
  550.          ((real_people->people[real_index & 4].id1 & 017) == inroll_direction)
  551.       &&
  552.          /* we do not have cw_end inrolling also */
  553.          ((real_people->people[real_index | 3].id1 & 017) != inroll_direction))
  554.       return(FALSE);
  555.    else {
  556.       fail("Can't find end looking in.");
  557.       /* NOTREACHED */
  558.   }
  559. }
  560.  
  561. /* ARGSUSED */
  562. static long_boolean magic_inroller_is_cw(setup *real_people, int real_index,
  563.    int real_direction, int northified_index)
  564. {
  565.    static int cw[8] = {3, 7, 7, 3, 7, 3, 3, 7};
  566.    static int cc[8] = {0, 4, 4, 0, 4, 0, 0, 4};
  567.    static int id[8] = {012, 010, 010, 012, 010, 012, 012, 010};
  568.    int inroll_direction;
  569.  
  570.    inroll_direction = id[real_index];
  571.    if (  /* cw_end exists and is inrolling */
  572.          ((real_people->people[cw[real_index]].id1 & 017) == inroll_direction)
  573.       &&
  574.          /* we do not have ccw_end inrolling also */
  575.          ((real_people->people[cc[real_index]].id1 & 017) != inroll_direction))
  576.       return(TRUE);
  577.    else if (
  578.          /* ccw_end exists and is inrolling */
  579.          ((real_people->people[cc[real_index]].id1 & 017) == inroll_direction)
  580.       &&
  581.          /* we do not have cw_end inrolling also */
  582.          ((real_people->people[cw[real_index]].id1 & 017) != inroll_direction))
  583.       return(FALSE);
  584.    else {
  585.       fail("Can't find end looking in.");
  586.       /* NOTREACHED */
  587.    }
  588. }
  589.  
  590. /* ARGSUSED */
  591. static long_boolean outroller_is_cw(setup *real_people, int real_index,
  592.    int real_direction, int northified_index)
  593. {
  594.    int outroll_direction;
  595.  
  596.    outroll_direction = 010 + ((real_index & 4) >> 1);
  597.    if (  /* cw_end exists and is outrolling */
  598.          ((real_people->people[real_index | 3].id1 & 017) == outroll_direction)
  599.       &&
  600.          /* we do not have ccw_end outrolling also */
  601.          ((real_people->people[real_index & 4].id1 & 017) != outroll_direction))
  602.       return(TRUE);
  603.    else if (
  604.          /* ccw_end exists and is outrolling */
  605.          ((real_people->people[real_index & 4].id1 & 017) == outroll_direction)
  606.       &&
  607.          /* we do not have cw_end outrolling also */
  608.          ((real_people->people[real_index | 3].id1 & 017) != outroll_direction))
  609.       return(FALSE);
  610.    else {
  611.       fail("Can't find end looking out.");
  612.       /* NOTREACHED */
  613.    }
  614. }
  615.  
  616. /* ARGSUSED */
  617. static long_boolean outposter_is_cw(setup *real_people, int real_index,
  618.    int real_direction, int northified_index)
  619. {
  620.    /* cw_end exists and is looking out */
  621.    return(((real_people->people[real_index | 3].id1 & 017) == (010 + ((real_index & 4) >> 1))));
  622. }
  623.  
  624. /* ARGSUSED */
  625. static long_boolean outposter_is_ccw(setup *real_people, int real_index,
  626.    int real_direction, int northified_index)
  627. {
  628.    /* ccw_end exists and is looking out */
  629.    return(((real_people->people[real_index & 4].id1 & 017) == (010 + ((real_index & 4) >> 1))));
  630. }
  631.  
  632. /* ARGSUSED */
  633. static long_boolean nexttrnglspot_is_tboned(setup *real_people, int real_index,
  634.    int real_direction, int northified_index)
  635. {
  636.    int z;
  637.    static int aa[4][3] = {
  638.       {-3, -2, -2}, {2, -2, 0}, {-3, 0, 0}, {1, 0, -2}};
  639.    int this_person = real_people->people[real_index].id1;
  640.  
  641.    z = aa[real_direction][real_index];
  642.    if (z < -2)
  643.       fail("Can't determine where to go or which way to face.");
  644.    else if (z == -2)
  645.       return(FALSE);
  646.    else {
  647.       z = real_people->people[z].id1;
  648.       if (z & BIT_PERSON)
  649.          return((z ^ this_person) & 1);
  650.       else {
  651.          fail("Can't determine where to go or which way to face.");
  652.      /* NOTREACHED */
  653.       }
  654.    }
  655. }
  656.  
  657. /* ARGSUSED */
  658. static long_boolean next62spot_is_tboned(setup *real_people, int real_index,
  659.    int real_direction, int northified_index)
  660. {
  661.    int z;
  662.    static int aa[4][6] = {
  663.       {-2, -3, -2, -2, -3, -2}, {-2, 2, -2, -2, 3, -2}, {-2, -3, -2, -2, -3, -2}, {-2, 0, -2, -2, 5, -2}};
  664.    int this_person = real_people->people[real_index].id1;
  665.  
  666.    z = aa[real_direction][real_index];
  667.    if (z < -2)
  668.       fail("Can't determine where to go or which way to face.");
  669.    else if (z == -2)
  670.       return(FALSE);
  671.    else {
  672.       z = real_people->people[z].id1;
  673.       if (z & BIT_PERSON)
  674.          return((z ^ this_person) & 1);
  675.       else {
  676.          fail("Can't determine where to go or which way to face.");
  677.      /* NOTREACHED */
  678.      }
  679.    }
  680. }
  681.  
  682. /* ARGSUSED */
  683. static long_boolean next_magic62spot_is_tboned(setup *real_people, int real_index,
  684.    int real_direction, int northified_index)
  685. {
  686.    int z;
  687.    static int aa[4][6] = {
  688.       {-3, -3, -3, -3, -3, -3}, {-2, 3, -2, -2, 2, -2}, {-3, -3, -3, -3, -3, -3}, {-2, 5, -2, -2, 0, -2}};
  689.    int this_person = real_people->people[real_index].id1;
  690.  
  691.    z = aa[real_direction][real_index];
  692.    if (z < -2)
  693.       fail("Can't determine where to go or which way to face.");
  694.    else if (z == -2)
  695.       return(FALSE);
  696.    else {
  697.       z = real_people->people[z].id1;
  698.       if (z & BIT_PERSON)
  699.          return((z ^ this_person) & 1);
  700.       else {
  701.          fail("Can't determine where to go or which way to face."); 
  702.          /* NOTREACHED */
  703.       }
  704.    }
  705. }
  706.  
  707. /* ARGSUSED */
  708. static long_boolean next_galaxyspot_is_tboned(setup *real_people, int real_index,
  709.    int real_direction, int northified_index)
  710. {
  711.    int z;
  712.    static int aa[4][8] = {
  713.       { 1,  2, -3,  2,  3,  4, -3,  0},
  714.       {-3,  2,  3,  4, -3,  4,  5,  6},
  715.       { 7,  0, -3,  4,  5,  6, -3,  6},
  716.       {-3,  0,  1,  2, -3,  6,  7,  0}};
  717.    int this_person = real_people->people[real_index].id1;
  718.  
  719.    /* We always return true for centers.  That way
  720.       the centers can reverse flip a galaxy even if the
  721.       next point does not exist.  Maybe this isn't a good way
  722.       to do it, and we need another predicate.  Sigh. */
  723.    if (real_index & 1) return(TRUE);
  724.  
  725.    z = aa[real_direction][real_index];
  726.    if (z >= -2) {
  727.       z = real_people->people[z].id1;
  728.       if (z & BIT_PERSON) return((z ^ this_person) & 1);
  729.    }
  730.    fail("Can't determine where to go or which way to face.");
  731.    /* NOTREACHED */
  732. }
  733.  
  734. /* ARGSUSED */
  735. static long_boolean column_double_down(setup *real_people, int real_index,
  736.    int real_direction, int northified_index)
  737. {
  738.    return(
  739.       (northified_index < 3)              /* unless #1 in column, it's easy */
  740.          ||
  741.       (northified_index > 4)
  742.          ||
  743.       /* if #1, my adjacent end must exist and face in */
  744.       (((((real_index + 2) & 4) ^ 1) + 1) == (real_people->people[real_index ^ 7].id1 & 017)));
  745. }
  746.  
  747. /* ARGSUSED */
  748. static long_boolean boyp(setup *real_people, int real_index,
  749.    int real_direction, int northified_index)
  750. {
  751.    if (initializing_database) return TRUE;
  752.    return((real_people->people[real_index].id2 & ID2_BOY) != 0);
  753. }
  754.  
  755. /* ARGSUSED */
  756. static long_boolean girlp(setup *real_people, int real_index,
  757.    int real_direction, int northified_index)
  758. {
  759.    if (initializing_database) return TRUE;
  760.    return((real_people->people[real_index].id2 & ID2_GIRL) != 0);
  761. }
  762.  
  763. /* ARGSUSED */
  764. static long_boolean roll_is_cw(setup *real_people, int real_index,
  765.    int real_direction, int northified_index)
  766. {
  767.    return((real_people->people[real_index].id1 & ROLLBITR) != 0);
  768. }
  769.  
  770. /* ARGSUSED */
  771. static long_boolean roll_is_ccw(setup *real_people, int real_index,
  772.    int real_direction, int northified_index)
  773. {
  774.    return((real_people->people[real_index].id1 & ROLLBITL) != 0);
  775. }
  776.  
  777. /* ARGSUSED */
  778. static long_boolean x12_boy_facing_girl(setup *real_people, int real_index,
  779.    int real_direction, int northified_index)
  780. {
  781.    int this_person = real_people->people[real_index].id2;
  782.    int other_person = real_people->people[real_index ^ 1].id2;
  783.    if (initializing_database) return TRUE;
  784.    return((this_person & ID2_BOY) && (other_person & ID2_GIRL));
  785. }
  786.  
  787. /* ARGSUSED */
  788. static long_boolean x12_girl_facing_boy(setup *real_people, int real_index,
  789.    int real_direction, int northified_index)
  790. {
  791.    int this_person = real_people->people[real_index].id2;
  792.    int other_person = real_people->people[real_index ^ 1].id2;
  793.    if (initializing_database) return TRUE;
  794.    return((this_person & ID2_GIRL) && (other_person & ID2_BOY));
  795. }
  796.  
  797. /* ARGSUSED */
  798. static long_boolean x22_boy_facing_girl(setup *real_people, int real_index,
  799.    int real_direction, int northified_index)
  800. {
  801.    int this_person = real_people->people[real_index].id2;
  802.    int other_person = real_people->people[real_index ^ (((real_direction << 1) & 2) ^ 3)].id2;
  803.    if (initializing_database) return TRUE;
  804.    return((this_person & ID2_BOY) && (other_person & ID2_GIRL));
  805. }
  806.  
  807. /* ARGSUSED */
  808. static long_boolean x22_girl_facing_boy(setup *real_people, int real_index,
  809.    int real_direction, int northified_index)
  810. {
  811.    int other_person = real_people->people[real_index ^ (((real_direction << 1) & 2) ^ 3)].id2;
  812.    int this_person = real_people->people[real_index].id2;
  813.    if (initializing_database) return TRUE;
  814.    return((this_person & ID2_GIRL) && (other_person & ID2_BOY));
  815. }
  816.  
  817. /* ARGSUSED */
  818. static long_boolean dmd_ctrs_rh(setup *real_people, int real_index,
  819.    int real_direction, int northified_index)
  820. {
  821.    if (real_people->people[1].id1 | real_people->people[3].id1) {
  822.       if (     (!real_people->people[1].id1 || (real_people->people[1].id1 & d_mask)==d_east) &&
  823.                (!real_people->people[3].id1 || (real_people->people[3].id1 & d_mask)==d_west) )
  824.          return(TRUE);
  825.       else if ((!real_people->people[1].id1 || (real_people->people[1].id1 & d_mask)==d_west) &&
  826.                (!real_people->people[3].id1 || (real_people->people[3].id1 & d_mask)==d_east) )
  827.          return(FALSE);
  828.    }
  829.  
  830.    fail("Can't determine handedness of centers.");
  831.    /* NOTREACHED */
  832. }
  833.  
  834. /* ARGSUSED */
  835. static long_boolean trngl_pt_rh(setup *real_people, int real_index,
  836.    int real_direction, int northified_index)
  837. {
  838.    if ((real_people->people[0].id1 & d_mask)==d_west)
  839.       return(TRUE);
  840.    else if ((real_people->people[0].id1 & d_mask)==d_east)
  841.       return(FALSE);
  842.  
  843.    fail("Can't determine handedness of triangle point.");
  844.    /* NOTREACHED */
  845. }
  846.  
  847. /* ARGSUSED */
  848. static long_boolean q_tag_front(setup *real_people, int real_index,
  849.    int real_direction, int northified_index)
  850. {
  851.    if (real_index & 2)
  852.       /* I am in the center line, see if I have a miniwave. */
  853.       return(((real_people->people[real_index].id1 ^ real_people->people[real_index ^ 1].id1) & DIR_MASK) == 2);
  854.    else {
  855.       /* I am on the outside; find the end of the center line nearest me. */
  856.       int z;
  857.       if (real_index & 1) z = real_index ^ 3; else z = real_index ^ 6;
  858.       return(((real_people->people[z].id1 & 017) == (010 + (real_index >> 1))) &&
  859.             (((real_people->people[z].id1 ^ real_people->people[z ^ 1].id1) & DIR_MASK) == 2));
  860.    }
  861. }
  862.  
  863. /* ARGSUSED */
  864. static long_boolean q_tag_back(setup *real_people, int real_index,
  865.    int real_direction, int northified_index)
  866. {
  867.    if (real_index & 2)
  868.       /* I am in the center line, see if I have a miniwave. */
  869.       return(((real_people->people[real_index].id1 ^ real_people->people[real_index ^ 1].id1) & DIR_MASK) == 2);
  870.    else {
  871.       /* I am on the outside; find the end of the center line nearest me. */
  872.       int z;
  873.       if (real_index & 1) z = real_index ^ 3; else z = real_index ^ 6;
  874.       return(((real_people->people[z].id1 & 017) == (012 - (real_index >> 1))) &&
  875.             (((real_people->people[z].id1 ^ real_people->people[z ^ 1].id1) & DIR_MASK) == 2));
  876.    }
  877. }
  878.  
  879. /* ARGSUSED */
  880. static long_boolean q_line_front(setup *real_people, int real_index,
  881.    int real_direction, int northified_index)
  882. {
  883.    if (real_index & 2)
  884.       /* I am in the center line, see if I have a couple. */
  885.       return(((real_people->people[real_index].id1 ^ real_people->people[real_index ^ 1].id1) & DIR_MASK) == 0);
  886.    else {
  887.       /* I am on the outside; find the end of the center line nearest me. */
  888.       int z;
  889.       if (real_index & 1) z = real_index ^ 3; else z = real_index ^ 6;
  890.       return(((real_people->people[z].id1 & 017) == (010 + (real_index >> 1))) &&
  891.             (((real_people->people[z].id1 ^ real_people->people[z ^ 1].id1) & DIR_MASK) == 0));
  892.    }
  893. }
  894.  
  895. /* ARGSUSED */
  896. static long_boolean q_line_back(setup *real_people, int real_index,
  897.    int real_direction, int northified_index)
  898. {
  899.    if (real_index & 2)
  900.       /* I am in the center line, see if I have a couple. */
  901.       return(((real_people->people[real_index].id1 ^ real_people->people[real_index ^ 1].id1) & DIR_MASK) == 0);
  902.    else {
  903.       /* I am on the outside; find the end of the center line nearest me. */
  904.       int z;
  905.       if (real_index & 1) z = real_index ^ 3; else z = real_index ^ 6;
  906.       return(((real_people->people[z].id1 & 017) == (012 - (real_index >> 1))) &&
  907.             (((real_people->people[z].id1 ^ real_people->people[z ^ 1].id1) & DIR_MASK) == 0));
  908.    }
  909. }
  910.  
  911. /* BEWARE!!  This list must track the array "predtab" in the database maker. */
  912.  
  913. /* The first 6 of these (the constant to use is SELECTOR_PREDS) take a predicate.
  914.    Any call that uses one of these predicates in its definition will cause a
  915.    popup to appear asking "who?". */
  916.  
  917. long_boolean (*pred_table[])(
  918.    setup *real_people,
  919.    int real_index,
  920.    int real_direction,
  921.    int northified_index) = {
  922.       selected,                        /* "select" */
  923.       unselect,                        /* "unselect" */
  924.       select_near_select,              /* "select_near_select" */
  925.       select_near_unselect,            /* "select_near_unselect" */
  926.       unselect_near_select,            /* "unselect_near_select" */
  927.       unselect_near_unselect,          /* "unselect_near_unselect" */
  928.       always,                          /* "always" */
  929.       x22_miniwave,                    /* "x22_miniwave" */
  930.       x22_couple,                      /* "x22_couple" */
  931.       x22_facing_someone,              /* "x22_facing_someone" */
  932.       x14_once_rem_miniwave,           /* "x14_once_rem_miniwave" */
  933.       x14_once_rem_couple,             /* "x14_once_rem_couple" */
  934.       opp_in_quad,                     /* "lines_miniwave" */
  935.       same_in_quad,                    /* "lines_couple" */
  936.       opp_in_magic,                    /* "lines_magic_miniwave" */
  937.       same_in_magic,                   /* "lines_magic_couple" */
  938.       lines_once_rem_miniwave,         /* "lines_once_rem_miniwave" */
  939.       lines_once_rem_couple,           /* "lines_once_rem_couple" */
  940.       same_in_pair,                    /* "lines_tandem" */
  941.       opp_in_pair,                     /* "lines_antitandem" */
  942.       same_in_quad,                    /* "columns_tandem" */
  943.       opp_in_quad,                     /* "columns_antitandem" */
  944.       same_in_magic,                   /* "columns_magic_tandem" */
  945.       opp_in_magic,                    /* "columns_magic_antitandem" */
  946.       lines_once_rem_couple,           /* "columns_once_rem_tandem" */
  947.       lines_once_rem_miniwave,         /* "columns_once_rem_antitandem" */
  948.       same_in_pair,                    /* "columns_couple" */
  949.       opp_in_pair,                     /* "columns_miniwave" */
  950.       x12_beau_or_miniwave,            /* "1x2_beau_or_miniwave" */
  951.       x14_wheel_and_deal_1,            /* "1x4_wheel_and_deal_1" */
  952.       x14_wheel_and_deal_2,            /* "1x4_wheel_and_deal_2" */
  953.       vert1,                           /* "vert1" */
  954.       vert2,                           /* "vert2" */
  955.       inner_active_lines,              /* "inner_active_lines" */
  956.       outer_active_lines,              /* "outer_active_lines" */
  957.       judge_is_right,                  /* "judge_is_right" */
  958.       judge_is_left,                   /* "judge_is_left" */
  959.       socker_is_right,                 /* "socker_is_right" */
  960.       socker_is_left,                  /* "socker_is_left" */
  961.       inroller_is_cw,                  /* "inroller_is_cw" */
  962.       magic_inroller_is_cw,            /* "magic_inroller_is_cw" */
  963.       outroller_is_cw,                 /* "outroller_is_cw" */
  964.       outposter_is_cw,                 /* "outposter_is_cw" */
  965.       outposter_is_ccw,                /* "outposter_is_ccw" */
  966.       nexttrnglspot_is_tboned,         /* "nexttrnglspot_is_tboned" */
  967.       next62spot_is_tboned,            /* "next62spot_is_tboned" */
  968.       next_magic62spot_is_tboned,      /* "next_magic62spot_is_tboned" */
  969.       next_galaxyspot_is_tboned,       /* "next_galaxyspot_is_tboned" */
  970.       column_double_down,              /* "column_double_down" */
  971.       boyp,                            /* "boyp" */
  972.       girlp,                           /* "girlp" */
  973.       roll_is_cw,                      /* "roll_is_cw" */
  974.       roll_is_ccw,                     /* "roll_is_ccw" */
  975.       x12_boy_facing_girl,             /* "x12_boy_facing_girl" */
  976.       x12_girl_facing_boy,             /* "x12_girl_facing_boy" */
  977.       x22_boy_facing_girl,             /* "x22_boy_facing_girl" */
  978.       x22_girl_facing_boy,             /* "x22_girl_facing_boy" */
  979.       dmd_ctrs_rh,                     /* "dmd_ctrs_rh" */
  980.       trngl_pt_rh,                     /* "trngl_pt_rh" */
  981.       q_tag_front,                     /* "q_tag_front" */
  982.       q_tag_back,                      /* "q_tag_back" */
  983.       q_line_front,                    /* "q_line_front" */
  984.       q_line_back};                    /* "q_line_back" */
  985.